<script setup>
import {  computed, nextTick, onMounted, ref, watch} from 'vue';
import ClassItem from '@/components/ClassItem.vue';
import { addTrain, deleteTrain, getTrainPlan, modifyTrain } from '@/api/train';
import { ElMessage, ElMessageBox } from 'element-plus';

const MAX_OFFSET = 1;
// 课程信息
const data = ref([])
// 记录周几有哪些课,供新增课程的校验
const projectIdHashSets = ref({
  "monday":new Set(),
  "tuesday":new Set(),
  "wednesday":new Set(),
  "thursday":new Set(),
  "friday":new Set(),
  "saturday":new Set(),
  "sunday":new Set(),
})

// 修改前的原老师数据,用于判断是否修改了
const originalTeacherList = ref({})
// 最早有课的时间
const earliestAvailableDate = ref('2024-08-01');
// 弹窗类型
const dialogType = ref(0) // 0表示新增弹窗,1表示编辑弹窗
// 弹窗可见
const dialogVisible = ref(false)
// 弹窗表格实例
const dialogFormRef = ref(null)
// 时间是否包含周末
const isContainsWeekend = ref(false)

const currentDateOffset = ref(0)
// 弹窗响应式数据
const dialogFormData = ref({
  classId: '',//课程ID
  projectId:'',//项目号
  companyName :'',//公司
  groupName :'',//集团
  systemName:'',//所属体系
  teacher:[],//培训老师
  period :'',//培训时间
  teachingContent:'' // 培训内容
})
// 计算最早有数据
const calculateMinOffset = computed(() => {
  const earliestDate = new Date(earliestAvailableDate.value);
  const currentDate = new Date();
  const timeDiff = currentDate - earliestDate;
  const minOffset = Math.floor(timeDiff / (1000 * 60 * 60 * 24 * 7));

  return minOffset;
});
// 高亮label
const highlightedLabel = ref('')
// 高亮key
const highlightedKey = ref('')

// 培训计划时间范围
const weekdaysNotWeekend = ref([
      { label: "Mon", key: "monday" },
      { label: "Tue", key: "tuesday" },
      { label: "Wed", key: "wednesday" },
      { label: "Thu", key: "thursday" },
      { label: "Fri", key: "friday" },]
);
const weekdaysHasWeekend = ref([
      { label: "Mon", key: "monday" },
      { label: "Tue", key: "tuesday" },
      { label: "Wed", key: "wednesday" },
      { label: "Thu", key: "thursday" },
      { label: "Fri", key: "friday" },
      { label: "Set", key: "saturday" },
      { label: "Sun", key: "sunday" },
    ]
);

// 当前显示的日期
const range = ref([])

const setRange = () => {
  const offset = isContainsWeekend.value ? 6 : 4;
  var date = new Date();
  // 本周一的日期


  date.setDate(date.getDate() - date.getDay() + 1 + currentDateOffset.value * 7);

  range.value[0] = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" +( date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) ;

  // 本周五的日期
  date.setDate(date.getDate() + offset);
  range.value[1] = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) ;
}

// 当前显示的日期
const rangeShow = computed(() => {
  return range.value[0] + ' ~ ' + range.value[1]
})
// 控制表头合并单元格
const headerCellStyle = ({ column, rowIndex, columnIndex }) =>  {
  if (columnIndex == 1 && rowIndex === 0) {
    return { display: "none" };
  }
  if ((rowIndex == 0) & (columnIndex == 0)) {
    nextTick(() => {
      document.querySelector(`.${column.id}`).setAttribute("colspan", "2");
    });
  }
  if(column.label === highlightedLabel.value && rowIndex != 1) {
    return  { backgroundColor: '#409eff' };
  }
}

    // span-method 方法来合并相同 companyName 的单元格
// span-method 方法来合并相同 companyName 的单元格
const spanMethod = ({ rowIndex, columnIndex }) =>  {
  const row = data.value[rowIndex];
  // 合并 companyName 相同的行
  if (columnIndex === 0) {
    let rowspan = 1;
    // 判断后续行的 companyName 是否与当前行的相同
    for (let i = rowIndex + 1; i < data.value.length; i++) {
      if (data.value[i].companyName === row.companyName) {
        rowspan++;
      } else {
        break;
      }
    }
    if (rowspan > 1) {
      // 如果有相同的 companyName，则合并这些单元格
      return { rowspan, colspan: 1 };
    } else {
      // 如果没有相同的 companyName，返回 colspan: 0 隐藏单元格
      if(rowIndex != 0 && data.value[rowIndex].companyName === data.value[rowIndex-1].companyName) {
        return { rowspan: 1, colspan: 0 };
      }
    }
  }

  // 对于其他列不做合并，默认每行每列都是独立的
  return { rowspan: 1, colspan: 1 };
}

// 编辑课程
const handleClassEdit = (obj) => {
  dialogType.value = 1;
  const date = new Date(obj.classTime)
  const dayOfWeek = date.getDay()

  highlightedKey.value = weekdaysHasWeekend.value[dayOfWeek - 1].key
  dialogFormData.value.classId = obj.id
  dialogFormData.value.projectId = obj.projectId
  const item = data.value.find((session) => {
    return session.projectId === obj.projectId
  })

  dialogFormData.value.companyName = item.companyName
  dialogFormData.value.groupName = item.groupName
  dialogFormData.value.systemName = obj.systemName
  dialogFormData.value.teacher = obj.trainer.map(trainer => trainer.id);
  dialogFormData.value.period = obj.trainer[0].period
  dialogFormData.value.teachingContent = obj.teachingContent
  dialogVisible.value = true
  originalTeacherList.value = []
  dialogFormData.value.teacher.forEach((item) => {
    originalTeacherList.value.push({id:item,period:obj.trainer[0].period})

  })
}

// 删除课程
const handleDel =  (id) => {
  ElMessageBox.confirm('你确定要删除该课程吗?? 注意! 此操作不可逆转')
    .then(async () => {
      try {
        await deleteTrain(id)
        ElMessage.success('删除成功')
        await getPlan()
      } catch (e) {
        ElMessage.error(e.message)
      }
  })
}
//选择表头
const handleHeaderCellClick = (column) => {
  if(column.children  && column.children.length == 1) {
    if(column.label === highlightedLabel.value) {
      highlightedLabel.value = ''
      highlightedKey.value = ''
    }else {
      highlightedLabel.value = column.label
      highlightedKey.value = column.rawColumnKey
    }
  }

}
watch(currentDateOffset,async () => {
  await getPlan()
})
// 更新map和set
const updateMapsAndSets = () => {
   projectIdHashSets.value = ({
  "monday":new Set(),
  "tuesday":new Set(),
  "wednesday":new Set(),
  "thursday":new Set(),
  "friday":new Set(),
  "saturday":new Set(),
  "sunday":new Set(),
})
  data.value.forEach(session => {
    if (session.monday) {
      projectIdHashSets.value.monday.add(session.monday.projectId)
    }
    if (session.tuesday) {
      projectIdHashSets.value.tuesday.add(session.tuesday.projectId)
    }
    if (session.wednesday) {
      projectIdHashSets.value.wednesday.add(session.wednesday.projectId)
    }
    if (session.thursday) {
      projectIdHashSets.value.thursday.add(session.thursday.projectId)

    }
    if (session.friday) {
      projectIdHashSets.value.friday.add(session.friday.projectId)

    }
    if (session.saturday) {
      projectIdHashSets.value.saturday.add(session.saturday.projectId)

    }
    if (session.sunday) {
      projectIdHashSets.value.friday.add(session.sunday.projectId)
    }
  })
}
// 查询函数
async function getPlan() {
  const res = await getTrainPlan(range.value[0], range.value[1], isContainsWeekend.value)
  data.value = res.trainPlan
  projectOptions.value = res.projectList
  teacherOptions.value = res.trainerList
  updateMapsAndSets()
}

onMounted(async () => {
    setRange()
    getPlan()
});



// 处理下一周
const changeWeekAdd = () => {
  if(currentDateOffset.value >= MAX_OFFSET) {
    ElMessage.warning("您最多只能排下周的课程")
    return
  }
  currentDateOffset.value += 1;
  setRange()
}



// 处理上一周
const changeWeekSub = () => {
  if(currentDateOffset.value <= -calculateMinOffset.value) {
    ElMessage.warning("这是最早有数据的一周")
    return
  }
  currentDateOffset.value -= 1;
  setRange()
}

// 处理新增
const handleAdd = () => {
  if(currentDateOffset.value < 0) {
    return ElMessage.warning("您不能为之前的时间排课")
  }
  dialogType.value = 0
  dialogVisible.value = true

}
// 项目数据选项
const projectOptions = ref([])
// 选中时
const handleOptionChange = (value) => {
    const project = projectOptions.value.find((item) => {
    return item.id === value
  })
  dialogFormData.value.companyName = project.companyName
  dialogFormData.value.groupName = project.groupName
  dialogFormData.value.systemName = project.systemName
}

// 教师选择数据
const teacherOptions = ref([])

// 培训时间数据
const periodOptions = ref([
  {key:0,value:'全天'},
  {key:1,value:'上午'},
  {key:2,value:'下午'},
])

// 点击提交
const handleSubmit = () => {
  dialogFormRef.value.validate(async (valid) => {
    if (!valid) {
      ElMessage.error('请填写正确的信息')
      return
    }
    // add
    if (dialogType.value === 0) {
          // 拿到时间
      const offset = weekdaysHasWeekend.value.findIndex((item) => {
        return item.label === highlightedLabel.value;
      });
      const time = new Date(range.value[0])
      time.setDate(time.getDate()+offset)
      const timeFormat = time.getFullYear() + '-' + ((time.getMonth() + 1) < 10 ? ('0' + (time.getMonth() + 1)) : (time.getMonth() + 1)) + "-" + (time.getDate() < 10 ? '0' + time.getDate() : time.getDate());

      const obj = {
        classTime:timeFormat,
        projectId:dialogFormData.value.projectId,
        teachingContent: dialogFormData.value.teachingContent,
        trainer:[]
      }
      dialogFormData.value.teacher.forEach((item) => {
        obj.trainer.push(
          {
            id: item,
            period: dialogFormData.value.period
          }
        )
      })
      try {
        await addTrain(obj)
        ElMessage.success('新增成功')
        await getPlan()
        dialogVisible.value = false
      } catch (e) {
        ElMessage.error(e.message)
      }
    } else {
      const change = getChangeField()

      if (Object.keys(change).length > 0) {
        const trainingSession = {
          id: dialogFormData.value.classId,
          teachingContent:change.teachingContent ? change.teachingContent : null,
        }

        if (change.trainer != null) {
          const tmp = []
          change.trainer.forEach((item) => {
            tmp.push({id:item})
          })
          trainingSession.trainer = tmp;
        } else {
          trainingSession.trainer = null;
        }
        console.log(change.period);

        if (change.period != null) {

          if (trainingSession.trainer != null) {
            trainingSession.trainer.forEach((item) => {
              item.period = change.period
            })
          } else {
            const tmp = []
            originalTeacherList.value.forEach((item) => {
              tmp.push({id:item.id,period:change.period})
            })

            trainingSession.trainer = tmp;
          }
        }
        try {

            await modifyTrain(trainingSession)
            ElMessage.success('修改成功')
          await getPlan()
            dialogVisible.value = false
        } catch (e) {
          ElMessage.error(e.message)
        }
      } else {
        ElMessage.info('没有修改任何数据')
      }
    }
    })
}

// 得到修改的字段
const getChangeField = () => {
  const originalDate = data.value.find((session) => {
    return session[highlightedKey.value] && session[highlightedKey.value].id === dialogFormData.value.classId
  })
  const change = {}
  if (originalTeacherList.value.length != dialogFormData.value.teacher.length) {
    change.trainer = dialogFormData.value.teacher
  } else {
    const arr1 = originalTeacherList.value.sort((a, b) => a.id - b.id);
    const arr2 = dialogFormData.value.teacher.sort((a, b) => a - b);

    for (let i = 0; i < arr1.length; i++) {
      if (arr1[i].id != arr2[i]) {
        change.trainer = dialogFormData.value.teacher
        break;
      }
    }
  }

  if (change.trainer || dialogFormData.value.period !== originalDate[highlightedKey.value].trainer[0].period) {
    change.period = dialogFormData.value.period
  }
  if (dialogFormData.value.teachingContent != originalDate[highlightedKey.value].teachingContent) {
    change.teachingContent = dialogFormData.value.teachingContent
  }

  return change
}
// 弹窗关闭
const handleDialogClose = () => {
  dialogFormData.value.classId = ''
  dialogFormData.value.projectId = ''
  dialogFormData.value.companyName = ''
  dialogFormData.value.groupName = ''
  dialogFormData.value.systemName = ''
  dialogFormData.value.teacher = []
  dialogFormData.value.period = ''
  dialogFormData.value.teachingContent = ''
  dialogFormRef.value.clearValidate()
  dialogVisible.value = false
  originalTeacherList.value = []
}
// 弹窗打开
const handleDialogOpen = async() => {
  updateMapsAndSets()
}
// 针对课程冲突的表单校验
const projectIdValidator = (rule, value, callback) => {
  if(dialogType.value === 1) {
         callback()
    }
  if (projectIdHashSets.value[highlightedKey.value].has(value)) {
    callback(new Error('该项目在该时间点已有课程安排'))
  } else {
    callback()
  }
}
// 针对时间段的表单校验
const periodValidator = (rule, value, callback) => {
  if (dialogFormData.value.teacher.length === 0) {
    callback()
  }
  const originalId = dialogFormData.value.classId;
  data.value.forEach((item) => {
    if (item[highlightedKey.value] != null) {
      console.log(item[highlightedKey.value]);

      item[highlightedKey.value].trainer.forEach((t) => {
        if ((item[highlightedKey.value].id != originalId)&&(dialogFormData.value.teacher.includes(t.id))&&(t.period === 0 || t.period === value)) {
          callback(new Error('有老师时间发生冲突'))
        }
      })
    }
  })
  callback()
}
// 表单校验
const formRule = {
  projectId: [
    { required: true, message: '请选择项目号', trigger: 'blur' },
    {validator: projectIdValidator,trigger:'change'}
  ],
  teacher: [
    { required: true, message: '请选择教师', trigger: 'blur' },

  ],
  period: [
    { required: true, message: '请选择时间段', trigger: 'blur' },
    {validator: periodValidator,trigger:'change'}

  ],
  teachingContent: [
    { required: true, message: '请输入培训内容', trigger: 'blur' }
  ],
}

watch(dialogVisible,(newVal) => {
  if(!newVal) {
    handleDialogClose()
  }
})
</script>

<template>
    <div class="home-container">
      <!-- add弹窗 -->
       <el-dialog  v-model="dialogVisible" systemName="新增计划" :before-close="handleDialogClose" @open="handleDialogOpen">
        <el-form ref="dialogFormRef" :model="dialogFormData" size="default" :rules="formRule">
          <el-form-item label="项目号" prop="projectId" >
            <el-select
              :disabled="dialogType === 1"
              v-model="dialogFormData.projectId"
              :multiple="false"
              filterable
              remote
              reserve-keyword
              placeholder="请选择项目号"
              @change="handleOptionChange"

            >
              <el-option
                v-for="item in projectOptions"
                :key="item.id"
                :value="item.id"
                :label="item.projectId"
              />
          </el-select>
          </el-form-item>
          <el-form-item label="公司" prop="companyName"><el-input v-model="dialogFormData.companyName" disabled></el-input></el-form-item>
          <el-form-item label="集团" prop="groupName"><el-input v-model="dialogFormData.groupName" disabled></el-input></el-form-item>
          <el-form-item label="所属体系" prop="systemName"><el-input v-model="dialogFormData.systemName" disabled></el-input></el-form-item>
          <el-form-item label="培训老师" prop="teacher">
            <el-select
              v-model="dialogFormData.teacher"
              multiple
              filterable
              remote
              reserve-keyword
              placeholder="请选择培训老师"
              value-key="id"
            >
              <el-option
                v-for="item in teacherOptions"
                :key="item.id"
                :value="item.id"
                :label="item.accountName"
              />
          </el-select>
          </el-form-item>
          <el-form-item label="培训时间" prop="period">
            <el-select
              v-model="dialogFormData.period"
              remote
              reserve-keyword
              placeholder="请选择培训时间"
            >
              <el-option
                v-for="item in periodOptions"
                :key="item.value"
                :value="item.key"
                :label="item.value"
              />
          </el-select>
        </el-form-item>
          <el-form-item label="培训内容" style="width: 100%;" prop="teachingContent">
            <el-input v-model="dialogFormData.teachingContent" placeholder=""
            type="textarea" :rows="5" maxlength="225" show-word-limit></el-input>
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="dialogVisible = false" size="default" >取消</el-button>
            <el-button type="primary" size="default" @click="handleSubmit">
              确定
            </el-button>
          </div>
        </template>
       </el-dialog>
      <div class="home-systemName">
        <h3>培训计划管理</h3>
      </div>
      <div class="inp">
        <div class="left">
          <el-form-item label="时间范围" size="default">
            <el-input v-model="rangeShow"  disabled=""></el-input>
          </el-form-item>
          <el-form-item>
            <el-checkbox label="是否包含周末" name="name" size="default" v-model="isContainsWeekend"></el-checkbox>
          </el-form-item>
          <el-button type="primary" size="default" @click="changeWeekSub">上一周</el-button>
          <el-button type="primary" size="default" @click="changeWeekAdd">下一周</el-button>
        </div>
        <div class="right">
          <el-button size="default">
            <el-icon><Download /></el-icon>导出
          </el-button>
          <el-button size="default">
            <el-icon><Message /></el-icon>邮件发送
          </el-button>
          <el-button size="default" :disabled="highlightedLabel === ''"
          @click="handleAdd">
            <el-icon><Plus /></el-icon>新增
          </el-button>
        </div>
      </div>
      <el-table :data="data" style="width: 100%"  :header-cell-style="headerCellStyle" size="small" :span-method="spanMethod"
      max-height="70vh"
      @header-click="handleHeaderCellClick"
      >
            <el-table-column header-align="center" align="center" prop="companyName" label="label" width="100px">
            </el-table-column>
            <el-table-column header-align="center" align="center" prop="groupName" label="label" width="100px">
            </el-table-column>
            <el-table-column v-for="(item)  in (isContainsWeekend ? weekdaysHasWeekend : weekdaysNotWeekend)" :key="item.key" :label="item.label"   align="center" >
              <el-table-column :prop="item.key" label="客户"  align="center"
              >
                <template #default="{row}">
                  <div style=" align-items: center" v-if="row[item.key]">
                    <ClassItem :classInfo="row[item.key]" @edit="handleClassEdit"  :isOp="true"
                    @del="handleDel"></ClassItem>
                  </div>
                  <div v-else>
                    暂无课程
                  </div>
                </template>
              </el-table-column>
            </el-table-column>
      </el-table>
    </div>
</template>

<style scoped lang="less">
.home-container {
  background-color: #fff;
  padding: 20px;
}
.home-systemName {
   h3 {
    font-weight: normal
   }
}

.table-systemName-time {
    padding: 20px 0;
    text-align: center;
    border: #ebeef5 1px solid;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
   }
   .inp {
    display: flex;
    justify-content: space-between;
    margin-top: 10px;
    .left {
      width: 50%;
      display: flex;
    }
    .el-form-item {
      margin-right: 10px;
    }
   }

   ::v-deep .el-form {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
::v-deep  .el-dialog .el-form-item  {
    display: block;
    width: 30%;
  }

  ::v-deep .el-dialog .el-form-item__label {
    color: black;
    font-size: 14px;
    margin-bottom: 5px;
  }
  ::v-deep .el-dialog .el-input__count {
  bottom: -15px !important;
}

</style>
